//
//Copyright 2001-2004 Stottler Henke Associates, Inc.
//All Rights Reserved.
////////////////////////////////////////////////////////////////////////////////

package com.stottlerhenke.simbionic.engine.parser;
import com.stottlerhenke.simbionic.common.*;
import com.stottlerhenke.simbionic.engine.*;
import com.stottlerhenke.simbionic.engine.file.SB_StreamReader;
import com.stottlerhenke.simbionic.api.*;
import com.stottlerhenke.simbionic.api.SB_Param;

/**
 * Represents a single variable of type float.
 */
public class SB_VarFloat extends SB_Variable
{

  public SB_VarFloat() {
    _parameterValue = new SB_Param( 0.0f );
  }
  
  public SB_VarFloat(float value){
    _parameterValue = new SB_Param( value );
  }
  
  public SB_VarFloat(SB_VarFloat var2)throws SB_Exception
  {
    Copy(var2);
  }
  
  private void Copy(SB_VarFloat var2) throws SB_Exception
  {
    _parameterValue = new SB_Param( var2.GetValue() );
  }
  
  public void SetValue(float value){
    _parameterValue.setFloat(value);
  }
  
  public SB_VarType GetType() { return SB_VarType.kFloat; }
  
  public void setSB_Param(SB_Param newParam) throws SB_Exception
  {
    newParam.getFloat();
    
    _parameterValue = newParam;
  }
  
  public float GetValue() throws SB_Exception
  {
    return _parameterValue.getFloat();
  }
  
  public SB_Variable opAssign(SB_VarFloat var) throws SB_Exception
  {
    if (this != var) {
      Copy(var);
    }
    return this;
  }
  
  public SB_Variable Clone() throws SB_Exception{
    return new SB_VarFloat(this);
  }
  
  public static float GET_FLOAT(SB_Variable var) throws SB_Exception
  {
    return ((SB_VarFloat)var).GetValue();
  }

  public void load(SB_StreamReader reader,SB_SingletonBook book)
		throws SB_Exception
	{
  	// this is really a pascal-style string
	  String expr = reader.readPString();
	  SB_Expression parsedExp = (SB_Expression)book.getParser().Parse(expr);

	  // evaluating the expression without passing in an entity or execution frame is
	  // only safe because the expression contains only constants!
	  SB_Variable expValue = parsedExp.Evaluate(null,null);
	  if (expValue.GetType() == SB_VarType.kFloat){
	    _parameterValue.setFloat( ((SB_VarFloat)expValue).GetValue() );
	  }
	  else if (expValue.GetType() == SB_VarType.kInteger){

	    _parameterValue.setFloat( ((SB_VarInteger)expValue).GetValue() );
	  }
	  else
	    throw new SB_Exception("Illegal initial value "+ expr +" for float variable.",EErrCode.kE_FORMAT);
	 }

   public SB_Variable opOr( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( (GetValue() != 0 ? true:false) || (GET_FLOAT(arg2) != 0 ? true:false) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( (GetValue() != 0 ? true:false) || (SB_VarInteger.GET_INTEGER(arg2) != 0 ? true:false) );
     else
       result = null;
        //FATAL( false, "Invalid operation on float variable");
     return result;
   }
  
   public SB_Variable opAND( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( (GetValue() != 0 ? true:false) && (GET_FLOAT(arg2) != 0 ? true:false) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( (GetValue() != 0 ? true:false) && (SB_VarInteger.GET_INTEGER(arg2) != 0 ? true:false) );
     else
       result = null;
       //FATAL( false, "Invalid operation on float variable");
     return result;
   }

   public SB_Variable opGRTEq( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if (arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() >= GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() >= SB_VarInteger.GET_INTEGER(arg2) );
     return result;
   }

   public SB_Variable opLSSEq( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() <= GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() <= SB_VarInteger.GET_INTEGER(arg2) );
     return result;
   }

   public SB_Variable opNOTEq( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() != GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() != SB_VarInteger.GET_INTEGER(arg2) );
     else if(arg2.GetType() == SB_VarType.kInvalid)
       result = new SB_VarBoolean( true );

     return result;
   }

   public SB_Variable equals( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() == GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() == SB_VarInteger.GET_INTEGER(arg2) );
     else if(arg2.GetType() == SB_VarType.kInvalid)
       result = new SB_VarBoolean( false );
     return result;
   }

   public SB_Variable opGRT( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() > GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() > SB_VarInteger.GET_INTEGER(arg2) );
     return result;
   }

   public SB_Variable opLSS( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarBoolean( GetValue() < GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarBoolean( GetValue() < SB_VarInteger.GET_INTEGER(arg2) );
     return result;
   }

   public SB_Variable opMOD( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarFloat( (float)fmod(GetValue(), GET_FLOAT(arg2)) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarFloat( (float)fmod(GetValue(), SB_VarInteger.GET_INTEGER(arg2)) );
     return result;
   }

   public SB_Variable opEXP( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

      if(arg2.GetType() == SB_VarType.kFloat)
        result = new SB_VarFloat( (float)Math.pow(GetValue(), GET_FLOAT(arg2)) );
      else if(arg2.GetType() == SB_VarType.kInteger)
        result = new SB_VarFloat( (float)Math.pow(GetValue(), SB_VarInteger.GET_INTEGER(arg2)) );
      return result;
   }

   public SB_Variable opDIV( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarFloat( GetValue() / GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarFloat( GetValue() / SB_VarInteger.GET_INTEGER(arg2) );
     return result;
   }

   public SB_Variable opMUL( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;

     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarFloat( GetValue() * GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarFloat( GetValue() * SB_VarInteger.GET_INTEGER(arg2) );
     else if(arg2.GetType() == SB_VarType.kVector){
       SB_Vector vector = SB_VarVector.GET_VECTOR(arg2);
       result = new SB_VarVector( vector.x * GetValue(),vector.y * GetValue(),vector.z * GetValue() );
      }

           return result;
   }

   public SB_Variable opSUB( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if(arg2.GetType() == SB_VarType.kFloat)
        result = new SB_VarFloat( GetValue() - GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
        result = new SB_VarFloat( GetValue() - SB_VarInteger.GET_INTEGER(arg2) );
      return result;
   }

   public SB_Variable opADD( SB_Variable arg2) throws SB_Exception  {
     SB_Variable result = null;
     if(arg2.GetType() == SB_VarType.kFloat)
       result = new SB_VarFloat( GetValue() + GET_FLOAT(arg2) );
     else if(arg2.GetType() == SB_VarType.kInteger)
       result = new SB_VarFloat( GetValue() + SB_VarInteger.GET_INTEGER(arg2) );
     else if(arg2.GetType() == SB_VarType.kString) // returns a concatenated string
     {
       String workStr;
       workStr =  Float.toString( GetValue()) + SB_VarString.GET_STRING(arg2);
       result = new SB_VarString( workStr );
      }
      return result;
   }

   public SB_Variable opNOT () throws SB_Exception {
           return new SB_VarBoolean( GetValue() == 0 );
   }

   public SB_Variable opNEG() throws SB_Exception {
           return new SB_VarFloat( -GetValue() );
   }

   public boolean bool() throws SB_Exception
   {
           return GetValue() != 0;
   }

   public static double fmod(double x, double y){
     return (x - ((int)(x/y))*y);
   }
   public String toString()
   {
     try
     {
       return Float.toString(GetValue());
     }
     catch(SB_Exception ex)
     {
       return ex.toString();
     }
   }
}